package com.mspbots.sync;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mspbots.api.client.CoreClient;
import com.mspbots.sync.model.ExceptionLog;
import com.mspbots.sync.model.Tenant;
import com.mspbots.sync.tsheets.SheetsProperties;
import com.mspbots.sync.wise.client.ClientProperties;
import com.mspbots.sync.wise.client.CwWebClient;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

/**
 * @author billb
 */
@Log4j2
public abstract class BaseGenericService {

    protected final String REDIS_KEY_PREFIX = "mspbots:sync:schedules:";

    protected RabbitMessagingTemplate messagingTemplate;

    protected ReactiveStringRedisTemplate stringRedisTemplate;
    protected ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;

    protected ObjectMapper objectMapper;
    protected CoreClient coreClient;
    protected CwWebClient cwWebClient;

    protected Mono<Tenant> onGetTenant(Integer tenantId) {
        return this.coreClient.get("/tenant/" + tenantId + "/info", null, Tenant.class);
    }

    public Mono<ClientProperties> onGetWiseProperties(Integer tenantId) {
        return this.onGetTenant(tenantId)
                .flatMap(tenant -> ClientProperties.build(tenant.getConfiguration()));
    }

    public Mono<SheetsProperties> onGetSheetProperties(Integer tenantId) {
        return this.onGetTenant(tenantId)
                .flatMap(tenant -> SheetsProperties.build(tenant.getConfiguration()));
    }


    protected void recordExceptionLog(Integer tenantId, int status, String type, String msg) {
        if (status != 200) {
            log.debug("Exception log from  {} api by tenant {},type:{},status code:{},Msg: {}",
                    "Tsheet", tenantId, type, status, msg);
        }
        this.messagingTemplate.convertAndSend("exception.log", ExceptionLog.builder()
                .tenantId(tenantId).name("Tsheet")
                .status(status).type(type).msg(msg).build());
    }

    protected void recordRedisValue(String key, String value) {
        this.stringRedisTemplate.opsForValue().set(REDIS_KEY_PREFIX + key, value).subscribe();
    }

    protected Mono<LocalDateTime> loadRedisValue(String key) {
        return this.stringRedisTemplate.opsForValue().get(REDIS_KEY_PREFIX + key)
                .map(LocalDateTime::parse)
                .defaultIfEmpty(LocalDateTime.now().minusDays(1));
    }

    @Autowired
    public void setCwWebClient(CwWebClient cwWebClient) {
        this.cwWebClient = cwWebClient;
    }

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Autowired
    public void setMessagingTemplate(RabbitMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    @Autowired
    public void setCoreClient(CoreClient coreClient) {
        this.coreClient = coreClient;
    }

    @Autowired
    public void setStringRedisTemplate(ReactiveStringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Autowired
    public void setReactiveRedisTemplate(ReactiveRedisTemplate<String, Object> redisTemplate) {
        this.reactiveRedisTemplate = redisTemplate;
    }

}
